/**
  ******************************************************************************
  * @file   pd_h_serial.c
  * @author Chris
  * @since  2023/11/22
  *
  * @brief  Peripheral driver of USART(Hardware-Implemented).
  *
  ******************************************************************************
  */
#include <stdio.h>
#include <stdarg.h>
#include "stm32g4xx_ll_bus.h"
#include "stm32g4xx_ll_rcc.h"
#include "stm32g4xx_ll_usart.h"
#include "pd_h_gpio.h"

/** region Declaration and Definition Region */

/** region Variables and Constants Region */
/** endregion Variables and Constants Region */

/** region Function Declaration Region */
/** endregion Function Declaration Region */

/** endregion Declaration and Definition Region */



/** region public function region */

/**
 * @brief   USART1 初始化
 *
 * @note    无
 * @retval  无
 */
void PD_H_USART1_Init(void) {
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);

    // 设置时钟源
    LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);

    // GPIO 初始化
    PD_H_GPIO_USART1_Init();

    // UART 配置
    LL_USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;      // 预分频
    USART_InitStruct.BaudRate = 9600;                               // 波特率（会根据预分频自动计算好后写入 BRR 寄存器）
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;             // 字长
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;                // 停止位
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;                 // 无校验
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;  // 发送、接收模式
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; // 硬件流控制
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;       // 采样
    LL_USART_Init(USART1, &USART_InitStruct);

    // 设置异步模式，清零 CR2、CR3 中的相关位
    LL_USART_ConfigAsyncMode(USART1);

    // NVIC 配置优先级
    NVIC_SetPriority(USART1_IRQn,
                     NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 1, 1));
    // 使能
    NVIC_EnableIRQ(USART1_IRQn);
    LL_USART_EnableIT_RXNE(USART1);

    LL_USART_Enable(USART1);

    // 等待 Transmit Enable Acknowledge 标志位
    while (!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1));
}

/**
 * @brief   USART1 发送一个字节
 *
 * @note    无
 * @param   byte 待发送的字节
 * @retval  无
 */
void PD_H_USART1_SendByte(uint8_t byte) {
    LL_USART_TransmitData8(USART1, byte);
    while (LL_USART_IsActiveFlag_TC(USART1) == RESET);
}

/**
 * @brief   USART1 发送数组
 *
 * @note    无
 * @param   array   待发送的数组
 * @param   length  待发送的数据长度
 * @retval  无
 */
void PD_H_USART1_SendArray(uint8_t *array, uint16_t length) {
    uint16_t i;
    for (i = 0; i < length; i++) {
        PD_H_USART1_SendByte(array[i]);
    }
}

/**
 * @brief   USART1 发送字符串
 *
 * @note    无
 * @param   String 待发送的字符串
 * @retval  无
 */
void PD_H_USART1_SendString(char *String) {
    uint8_t i;
    for (i = 0; String[i] != '\0'; i++) {
        PD_H_USART1_SendByte(String[i]);
    }
}

/**
 * @brief   USART1 发送一个字节
 *
 * @note    无
 * @param   x 底数
 * @param   y 指数
 * @retval  无
 */
uint32_t PD_H_USART1_Pow(uint32_t x, uint32_t y) {
    uint32_t result = 1;
    while (y--) {
        result *= x;
    }
    return result;
}

/**
 * @brief   USART1 发送一个字节
 *
 * @note    无
 * @param   number 待发送的字节
 * @param   length 待发送的字节
 * @retval  无
 */
void PD_H_USART1_SendNumber(uint32_t number, uint8_t length) {
    uint8_t i;
    for (i = 0; i < length; i++) {
        PD_H_USART1_SendByte(number / PD_H_USART1_Pow(10, length - i - 1) % 10 + '0');
    }
}

/**
 * @brief   USART1 发送一个字节
 *
 * @note    无
 * @param   byte 待发送的字节
 * @retval  无
 */
void PD_H_USART1_Printf(char *format, ...) {
    char String[100];
    va_list arg;
    va_start(arg, format);
    vsprintf(String, format, arg);
    va_end(arg);
    PD_H_USART1_SendString(String);
}


uint8_t Serial_RxFlag;
uint8_t Serial_RxData;

/**
 * @brief   USART1 接收数据完成标志
 *
 * @note    无
 * @retval  1，接收到数据；0，无数据
 */
uint8_t Serial_GetRxFlag(void) {
    if (Serial_RxFlag == 1) {
        Serial_RxFlag = 0;
        return 1;
    }
    return 0;
}

uint8_t Serial_GetRxData(void) {
    return Serial_RxData;
}

/**
 * @brief   USART1 中断服务函数
 *
 * @note    USART_ISR->RXNE 置 1：数据移位寄存器中的数据传送到接收数据寄存器中
 *          USART_ISR->RXNE 清 0：从接收数据寄存器读取数据，或者将 USART_RQR->RXFRQ 置 1
 * @retval  无
 */
void USART1_IRQHandler(void) {
    Serial_RxData = LL_USART_ReceiveData8(USART1);
    Serial_RxFlag = 1;
}

/** endregion public function region */



/** region private function region */

#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE {
    PD_H_USART1_SendByte(ch);
    return ch;
}
/** endregion private function region */
